#include <cstddef>
#include <cstdint>

namespace My 
{
    // 内存块的头部
    struct BlockHeader
    {
        // union-ed with data
        BlockHeader* pNext;     // 指向下一个内存块的指针
    };

    // 内存页的头部
    struct PageHeader
    {
        PageHeader* pNext;      // 包含指向下一个内存页的指针

        // 获取该页的第一个内存块
        BlockHeader* Blocks()
        {
            return reinterpret_cast<BlockHeader*>(this + 1);
        }
    };
    
    // 内存分配器
    class Allocator
    {
    public:
        Allocator();
        Allocator(size_t data_size, size_t page_size, size_t alignment);
        ~Allocator();

        // 使用新属性重置分配器
        void Rest(size_t data_size, size_t page_size, size_t alignment);

        // 分配和释放内存块
        void* Allocate();
        void Free(void* p);
        void FreeAll();

    public:
        // debug 模式
        static const uint8_t PATTERN_ALIGN = 0XFC;
        static const uint8_t PATTERN_ALLOC = 0XFD;
        static const uint8_t PATTERN_FREE = 0XFE;

    private:
        // 获取下一个内存块
        BlockHeader* NextBlock(BlockHeader* pBlock);

    private:
#if defined(_DEBUG)
        // debug模式下填充空闲内存页
        void FillFreePage(PageHeader* pPage);

        // debug模式下填充空闲内存块
        void FillFreeBlock(BlockHeader* pBlock);

        // debug模式下填充已分配的内存块
        void FillAllocatedBlock(BlockHeader* pBlock);
#endif
    
    private:
        PageHeader*     m_pPageList;        // 当前页地址
        BlockHeader*    m_pFreeList;        // 当前空闲块地址

        size_t          m_szDataSize;       // 数据大小
        size_t          m_szPageSize;       // 页大小
        size_t          m_szAlignmentSize;  // 对齐大小
        size_t          m_szBlockSize;      // 块大小
        size_t          m_nBlocksPerPage;   // 每页中块的数量

        size_t          m_nPages;           // 页数量
        size_t          m_nBlocks;          // 块数量
        size_t          m_nFreeBlocks;      // 空闲块数量

    private:
        // 禁止该本类型对象进行复制和赋值
        Allocator(const Allocator& clone);
        Allocator& operator=(const Allocator& rhs);
    };
}